#ifndef FIM_H
#define FIM_H
/*
//|----------------------------------------------------------------------------
//|                 SKY NETWORKS CONFIDENTIAL - COPYRIGHT 2016
//|----------------------------------------------------------------------------
//| The information contained herein is the property of Sky Networks and is
//| strictly confidential. Except as expressly authorized in writing by Sky
//| Networks, the holder shall keep all information contained herein confiden-
//| tial, shall disclose it only to its employees with a need to know, and
//| shall protect it, in whole or in part, from disclosure and dissemination
//| to third parties with the same degree of care it uses to protect its own
//| confidential information of like nature, but with no less than reasonable
//| care. Except expressly authorized in writing by Sky Networks, the holder
//| is granted no rights to use the information contained herein.
//|----------------------------------------------------------------------------
//|----------------------------------------------------------------------------
*/

#define DEFAULT_CONFIG_FILE "/usr/bin/fim_config"
#define MAX_RUNLEVEL 10
#define MIN_RUNLEVEL 0
#define NUM_STRIKEOUT 3

/*----------------------------------------------------------------------------
//  Forward Declarations
//--------------------------------------------------------------------------*/

typedef uint32_t  msgIdNt;
typedef uint16_t  msgSequenceNt;
typedef uint32_t  msgControlNt;
typedef ssize_t   msgLengthNt;

/** Message header */ 
typedef struct msgHeaderNt 
{ 
  union {
      msgIdNt     id;            /**< Unique message type, refer to <card>MsgId.h */
      msgIdNt     type;          /**< Obsolete, please don't use */
  };
  msgLengthNt     length;        /**< Total message length */ 
  msgControlNt    control;       /**< Misc. control bits, Ack and Nack bits */
  msgSequenceNt   sequence;      /**< Msg seq number, used to generate a unique header */ 
  msgSequenceNt   sequenceReply; /**< Msg seq reply number, used to generate a unique header */ 
  struct timeval  txTime;        /**< Message tx time */ 
  struct timeval  rxTime;        /**< Message rx time */ 
  struct timeval  timeReply;     /**< Message reply time */
}__attribute__ ((packed)) msgHeaderNt_t;

/* This message causes FIM to dump a list of FDs and their status to syslog */
#define MAX_STATUS_SIZE 255
struct fimStatusNt
{
  struct msgHeaderNt header;
  uint16_t max_size;
  char statusString[MAX_STATUS_SIZE];
};

#define FIM_STATUS     MSG_ID('F',0, 0, sizeof(struct fimStatusNt))
#define FIM_STATUS_END MSG_ID('F',1, 0, 0)

/* This message causes FIM to terminate all FDs and itself */
#define FIM_TERMINATE  MSG_ID('F',2, 0, 0)

/* This message causes FIM to move to a certain run-level - run level
 * can only be increased - not decreased
 */
struct fimRunLevelNt
{
  struct msgHeaderNt   header;
  uint16_t runLevel;
};

#define FIM_RUNLEVEL   MSG_ID('F',3, sizeof(struct fimRunLevelNt), 0)

/* This message will cause the FIM to send out sanity messages to all
 * the initialized components
 */
struct fimSanityNt
{
  struct msgHeaderNt   header;
};

#define FIM_SANITY_ALARM  MSG_ID('F',5,sizeof(struct fimSanityNt), 0)

#define FIM_DONTKILL   MSG_ID('F',6, 0, 0)

#define MSG_GROUP_COMMON  'C'

#define MSG_COMMON_SANITY  MSG_ID(MSG_GROUP_COMMON,2,0,sizeof(struct msgHeaderNt))

#define _COM_DEFAULT_PATH           "/tmp/"
#define COMM_FIM                    _COM_DEFAULT_PATH"fim"
#define COMM_FIM_P                  _COM_DEFAULT_PATH"fim_p"

#define MSG_MAX_PAYLOAD_LEN (1500)
#define MSG_MAX_LEN         (MSG_MAX_PAYLOAD_LEN + sizeof(msgHeaderNt_t)) 

/** Message control */
#define MSG_CONTROL_ACK  (1 << 0)
#define MSG_CONTROL_NACK (1 << 1)

/*
 * Name:
 *    msg_control_set (inline)
 *
 * Description:
 *    This function set the control field in the message header
 *
 *    |3                            0|   0    |   0   |
 *    |1                            2|   1    |   0   |
 *    |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|CNTLNACK|CNTLACK|
 *
 * Parameters:
 *    buf - Control buffer
 *    control - Bit to set.
 */
static __inline__ void msg_control_set
(
  msgControlNt * buf, 
  msgControlNt   control
)
{
  switch(control)
  {
    case MSG_CONTROL_ACK:
      *buf |= MSG_CONTROL_ACK;
      *buf &= ~MSG_CONTROL_NACK;
      break;
    case MSG_CONTROL_NACK:
      *buf |= MSG_CONTROL_NACK;
      *buf &= ~MSG_CONTROL_ACK;
      break;
    default:
      break;    
  }
}

/*----------------------------------------------------------------------------
//  Type Declarations
//--------------------------------------------------------------------------*/
#include <sys/queue.h>

struct fim_sched
{
  int policy;
  int priority;
};

struct process_data
{
  char const *         name;
  char const *         cmd;
  char * const *       args;
  char const *         sock_name;
  uint32_t             run_level;
  int                  strikeout;
  int                  restart_count;
  uint32_t             save_stdout;
  int                  num_restarted;
  unsigned long int    affinity;
  struct fim_sched     fsched;
  pid_t                pid;
  struct timeval       sanityTimestamp; 
  LIST_ENTRY(process_data) scan_entries;
  LIST_ENTRY(process_data) sanity_entries;
};

struct fim_options {
  char vmajor;
  char vminor;
  char date[64];
  bool timestamp;
  int default_log_level;
  int default_stdout_msg;
  int local_fd;
  struct sockaddr_un  local_addr;
  int  scheduling;
  int prio_max;
  int prio_min;
  unsigned long corelimit;
  char * fd_path;
  char * cfile;
  bool status;
  bool terminate;
  bool dontkill;
  bool main;
  int  start_level;
  int  run_level;
  int  socket;
  uint16_t current_level;
};

int fim_create_socket(const char * sock_name);
int fim_send_to(int fd,const char * sock_name,const void * buffer,int length, int retry);
int fimp_main(struct fim_options * in);
int fim_main(struct fim_options * mv);

#define INIT_TIMER_SEC 10     //seconds
#define RECOVERY_TIMER_SEC 15 //seconds
#define SANITY_TIMER_SEC 20   //seconds

#endif  /* FIM_H */
